<template>
  <div>
    <el-table
      :data="tableData"
      :span-method="arraySpanMethod"
      border
      style="width: 100%"
      id="selectTable"
    >
      <el-table-column prop="id" label="ID" width="180"> </el-table-column>
      <el-table-column prop="name" label="姓名"> </el-table-column>
      <el-table-column prop="amount1" sortable label="数值 1">
      </el-table-column>
      <el-table-column prop="amount2" sortable label="数值 2">
      </el-table-column>
      <el-table-column prop="amount3" sortable label="数值 3">
      </el-table-column>
    </el-table>
    <el-button type="primary" @click="exportExcel">xslx导出</el-button>
    <el-button type="primary" @click="exportExcelCopy"
      >xlsx + xlsx-js-style导出</el-button
    >
  </div>
</template>
<script>
// 引入导出表格的依赖包
import * as XLSX from "xlsx";
import XLSXS from "xlsx-js-style";
import FileSaver from "file-saver";
export default {
  data() {
    return {
      tableData: [
        {
          id: "12987122",
          name: "王小虎",
          amount1: "234",
          amount2: "3.2",
          amount3: 10,
        },
        {
          id: "12987123",
          name: "王小虎",
          amount1: "165",
          amount2: "4.43",
          amount3: 12,
        },
        {
          id: "12987124",
          name: "王小虎",
          amount1: "324",
          amount2: "1.9",
          amount3: 9,
        },
        {
          id: "12987125",
          name: "王小虎",
          amount1: "621",
          amount2: "2.2",
          amount3: 17,
        },
        {
          id: "12987126",
          name: "王小虎",
          amount1: "539",
          amount2: "4.1",
          amount3: 15,
        },
      ],
      selectData: [],
      selectDialogType: false,
    };
  },
  methods: {
    // el-table 合并单元格
    arraySpanMethod({ row, column, rowIndex, columnIndex }) {
      if (rowIndex % 2 === 0) {
        if (columnIndex === 0) {
          return [1, 2];
        } else if (columnIndex === 1) {
          return [0, 0];
        }
      }
    },
    // 导出方法 - xlsx
    // 简单版本  无法设置样式
    exportExcel() {
      // 文件名称
      let excelTitle =  "表格数据";
      // 使用XLSX库的table_to_book方法，将指定的HTML表格数据转换为一个工作簿对象wb。
      let wb = XLSX.utils.table_to_book(document.querySelector("#selectTable"));
      // 使用XLSX库的write方法，将工作簿对象wb转换为Excel文件的二进制数据wbout。
      let wbout = XLSX.write(wb, {
        bookType: "xlsx",
        bookSST: true,
        type: "array",
      });
      // 使用FileSaver库的saveAs方法，将wbout保存为一个Excel文件，并指定文件名为excelTitle + ".xlsx"
      try {
        FileSaver.saveAs(
          new Blob([wbout], { type: "application/octet-stream" }),
          excelTitle + ".xlsx"
        );
      } catch (e) {
        if (typeof console !== "undefined") console.log(e, wbout);
      }
      // 返回Excel文件的二进制数据wbout。
      return wbout;
    },

    // -------------------------  分割线  --------------------------

    // 在 exportExcel 基础上优化
    exportExcelCopy() {
      // 可设置样式版本

      //       // 将数据源转成我们需要的二维数组
      //       const body = this.tableData.map((x) => [
      //         {
      //           v: x.id,
      //           t: "s",
      //           s: {
      //             // font 字体属性
      //             font: {
      //               bold: false,
      //               sz: 14,
      //               name: "宋体",
      //             },
      //             // alignment 对齐方式
      //             alignment: {
      //               vertical: "center", // 垂直居中
      //               horizontal: "center", // 水平居中
      //             },
      //             // fill 颜色填充属性
      //             fill: {
      //               fgColor: { rgb: "87CEEB" },
      //             },
      //           },
      //         },
      //         x.name,
      //         x.amount1,
      //         x.amount2,
      //         x.amount3,
      //       ]);

      //       /* 定义表头
      //     定义表头，每一行即是一个数组，数组中的元素即是一个个单元格内容。
      //     如果单元格不需要样式，那么每个元素类型为字符串即可。如：['表格'],
      //     如果单元格需要样式，那么数组中的元素就需要为一个个对象，在此对象中定义单元格的样式等等。
      //     这里只针对第一行进行举例：
      // */

      //       const header = [
      //         [
      //           {
      //             v: "表格",
      //             t: "s",
      //             s: {
      //               // font 字体属性
      //               font: {
      //                 bold: false,
      //                 sz: 14,
      //                 name: "宋体",
      //               },
      //               // alignment 对齐方式
      //               alignment: {
      //                 vertical: "center", // 垂直居中
      //                 horizontal: "center", // 水平居中
      //               },
      //               // fill 颜色填充属性
      //               fill: {
      //                 fgColor: { rgb: "87CEEB" },
      //               },
      //             },
      //           },
      //         ],
      //         [
      //           {
      //             v: "信息",
      //             t: "s",
      //             s: {
      //               // font 字体属性
      //               font: {
      //                 name: "宋体",
      //               },
      //               // alignment 对齐方式
      //               alignment: {
      //                 vertical: "center", // 垂直居中
      //                 horizontal: "center", // 水平居中
      //               },
      //               // fill 颜色填充属性
      //               fill: {
      //                 fgColor: { rgb: "FFC0CB" },
      //               },
      //               border: {
      //                 top: {
      //                   style: "thin", // "thin"：细线  "medium"：中等粗细线  "thick"：粗线
      //                   color: { rgb: "000000" }, // 设置边框线颜色为黑色
      //                 },
      //                 bottom: {
      //                   style: "thin",
      //                   color: { rgb: "000000" },
      //                 },
      //                 left: {
      //                   style: "thin",
      //                   color: { rgb: "000000" },
      //                 },
      //                 right: {
      //                   style: "thin",
      //                   color: { rgb: "000000" },
      //                 },
      //               },
      //             },
      //           },
      //           {
      //             v: "",
      //             t: "s",
      //             s: {
      //               // font 字体属性
      //               font: {
      //                 name: "宋体",
      //               },
      //               // alignment 对齐方式
      //               alignment: {
      //                 vertical: "center", // 垂直居中
      //                 horizontal: "center", // 水平居中
      //               },
      //               // fill 颜色填充属性
      //               fill: {
      //                 fgColor: { rgb: "FFC0CB" },
      //               },
      //               border: {
      //                 top: {
      //                   style: "thin", // "thin"：细线  "medium"：中等粗细线  "thick"：粗线
      //                   color: { rgb: "000000" }, // 设置边框线颜色为黑色
      //                 },
      //                 bottom: {
      //                   style: "thin",
      //                   color: { rgb: "000000" },
      //                 },
      //                 left: {
      //                   style: "thin",
      //                   color: { rgb: "000000" },
      //                 },
      //                 right: {
      //                   style: "thin",
      //                   color: { rgb: "000000" },
      //                 },
      //               },
      //             },
      //           },
      //           {
      //             v: "数值",
      //             t: "s",
      //             s: {
      //               // font 字体属性
      //               font: {
      //                 name: "宋体",
      //               },
      //               // alignment 对齐方式
      //               alignment: {
      //                 vertical: "center", // 垂直居中
      //                 horizontal: "center", // 水平居中
      //               },
      //               // fill 颜色填充属性
      //               fill: {
      //                 fgColor: { rgb: "FFC0CB" },
      //               },
      //             },
      //           },
      //         ],
      //         ["ID", "姓名", "数值1", "数值2", "数值3"],
      //       ];

      //       body.unshift(...header); // 将定义好的表头添加到 body 中
      //       const sheet = XLSX.utils.aoa_to_sheet(body); // aoa_to_sheet 将二维数组转成 sheet

      //       // 设置合并单元格
      //       const merges = [
      //         // s 表示起始位置，e 表示结束位置，r 表示行索引，c 表示列索引。
      //         { s: { r: 0, c: 0 }, e: { r: 0, c: 4 } },
      //         { s: { r: 1, c: 0 }, e: { r: 1, c: 1 } },
      //         { s: { r: 1, c: 2 }, e: { r: 1, c: 4 } },
      //         { s: { r: 3, c: 0 }, e: { r: 3, c: 1 } },
      //         { s: { r: 5, c: 0 }, e: { r: 5, c: 1 } },
      //         { s: { r: 7, c: 0 }, e: { r: 7, c: 1 } },
      //       ];
      //       sheet["!merges"] = merges; // 将merges添加到sheet中

      //       // 设置列宽
      //       const cols = [
      //         { wch: 10 },
      //         { wch: 10 },
      //         { wch: 10 },
      //         { wch: 10 },
      //         { wch: 10 },
      //         { wch: 10 },
      //         { wch: 10 },
      //       ];
      //       sheet["!cols"] = cols; // 将cols添加到sheet中

      //       //
      //       const rows = [{ hpx: 20 }, { hpx: 16 }, { hpx: 18 }];
      //       sheet["!rows"] = rows; // 将rows添加到sheet中，设置行高

      //       const workbook = XLSXS.utils.book_new(); // 创建虚拟的 workbook
      //       XLSXS.utils.book_append_sheet(workbook, sheet, "sheet名称"); // 向 workbook 中添加 sheet
      //       XLSXS.writeFile(workbook, "excel名称.xlsx"); // 导出 workbook

      //  --------   上边是不抽离方法的示例 ----------------
      // ----------  分割线 ----------------
      // ----------  下边是抽离了公共方法的示例 ----------------

      // 将数据源转成我们需要的二维数组
      const body = this.tableData.map((x) =>
        this.xlsxCellStyle([
          { text: x.id, fill: { fgColor: { rgb: "87CEEB" } } },
          { text: x.name },
          { text: x.amount1 },
          { text: x.amount2 },
          { text: x.amount3 },
        ])
      );

      /* 定义表头
    定义表头，每一行即是一个数组，数组中的元素即是一个个单元格内容。
    如果单元格不需要样式，那么每个元素类型为字符串即可。如：['表格'], 
    如果单元格需要样式，那么数组中的元素就需要为一个个对象，在此对象中定义单元格的样式等等。
    这里只针对第一行进行举例：
*/

      const header = [
        this.xlsxCellStyle([
          {
            text: "表格",
            font: {
              name: "宋体",
              size: 14,
              bold: true,
              italic: true,
              underline: true,
              color: "#FF0000",
            },
            fill: {
              fgColor: { rgb: "87CEEB" }, // 前景色，即填充颜色
            },
          },
        ]),

        this.xlsxCellStyle([
          {
            text: "信息",
            fill: { fgColor: { rgb: "FFC0CB" } },
            border: "auto",
          },
          { text: "", border: "auto" },
          { text: "数值", fill: { fgColor: { rgb: "FFC0CB" } } },
        ]),
        this.xlsxCellStyle([
          { text: "ID" },
          { text: "姓名" },
          { text: "数值1" },
          { text: "数值2" },
          { text: "数值3" },
        ]),
      ];

      body.unshift(...header); // 将定义好的表头添加到 body 中
      const sheet = XLSX.utils.aoa_to_sheet(body); // aoa_to_sheet 将二维数组转成 sheet

      // 设置合并单元格
      const merges = [
        // s 表示起始位置，e 表示结束位置，r 表示行索引，c 表示列索引。
        { s: { r: 0, c: 0 }, e: { r: 0, c: 4 } },
        { s: { r: 1, c: 0 }, e: { r: 1, c: 1 } },
        { s: { r: 1, c: 2 }, e: { r: 1, c: 4 } },
        { s: { r: 3, c: 0 }, e: { r: 3, c: 1 } },
        { s: { r: 5, c: 0 }, e: { r: 5, c: 1 } },
        { s: { r: 7, c: 0 }, e: { r: 7, c: 1 } },
      ];
      sheet["!merges"] = merges; // 将merges添加到sheet中

      // 设置列宽
      const cols = [
        { wch: 10 },
        { wch: 10 },
        { wch: 10 },
        { wch: 10 },
        { wch: 10 },
        { wch: 10 },
        { wch: 10 },
      ];
      sheet["!cols"] = cols; // 将cols添加到sheet中

      //
      const rows = [{ hpx: 20 }, { hpx: 16 }, { hpx: 18 }];
      sheet["!rows"] = rows; // 将rows添加到sheet中，设置行高

      const workbook = XLSXS.utils.book_new(); // 创建虚拟的 workbook
      XLSXS.utils.book_append_sheet(workbook, sheet, "sheet名称"); // 向 workbook 中添加 sheet
      XLSXS.writeFile(workbook, "excel名称.xlsx"); // 导出 workbook
    },
    // 自定义xlsx单元格样式
    xlsxCellStyle(value) {
      let arr = value.map((x) => {
        return {
          v: x.text || "",
          t: "s",
          s: {
            font: x.font || {
              name: "宋体", // 字体名称
              size: 14, // 字体大小
              bold: false, // 是否加粗
              italic: false, // 是否斜体
              underline: false, // 是否下划线
              color: "#FF0000", // 字体颜色
            },
            alignment: x.alignment || {
              horizontal: "center", // 水平对齐方式，可选值："left", "center", "right"
              vertical: "center", // 垂直对齐方式，可选值："top", "center", "bottom"
              wrapText: true, // 是否自动换行
            },
            fill: x.fill || "",
            // {
            // type: "pattern", // 填充类型，可选值："pattern", "gradient"
            // patternType: "solid", // 图案类型，可选值："solid", "darkGray", "lightGray", "mediumGray", "gray125", "gray0625"
            // fgColor: "#FFFF00", // 前景色，即填充颜色
            // bgColor: "#0000FF", // 背景色
            // }
            border: x.border
              ? x.border !== "auto"
                ? x.border
                : {
                    top: {
                      style: "thin", // "thin"：细线  "medium"：中等粗细线  "thick"：粗线
                      color: { rgb: "000000" }, // 设置边框线颜色为黑色
                    },
                    bottom: {
                      style: "thin",
                      color: { rgb: "000000" },
                    },
                    left: {
                      style: "thin",
                      color: { rgb: "000000" },
                    },
                    right: {
                      style: "thin",
                      color: { rgb: "000000" },
                    },
                  }
              : "",
          },
        };
      });
      return arr;
    },
  },
};
</script>